"""
个人中心相关API路由
"""
from datetime import datetime, timedelta
from typing import Any, Optional, List
from fastapi import APIRouter, Depends, HTTPException, status, UploadFile, File, Request, Query
from motor.motor_asyncio import AsyncIOMotorDatabase
from bson import ObjectId
import os
import uuid
from pathlib import Path

from app.api.deps import get_db, get_current_user
from app.models.user import UserUpdate
from app.models.notification import NotificationSettings, NotificationSettingsResponse
from app.models.activity import ActivityLogList, LoginLogList
from app.models.stats import UserStatsResponse, DashboardStats
from app.models.preferences import UserPreferences, UserPreferencesUpdate
from app.core.config import settings
from app.core.response import success_response, error_response, ApiResponse
import logging

logger = logging.getLogger(__name__)

router = APIRouter()

@router.get("/me", response_model=ApiResponse, summary="获取当前用户信息")
async def get_current_user_profile(
    current_user: dict = Depends(get_current_user),
    db: AsyncIOMotorDatabase = Depends(get_db)
) -> Any:
    """
    获取当前用户详细信息
    """
    try:
        user_id = ObjectId(current_user["user_id"])
        user = await db.users.find_one({"_id": user_id})
        
        if not user:
            return error_response(
                error_type="NOT_FOUND_ERROR",
                message="用户不存在",
                code=status.HTTP_404_NOT_FOUND
            )
        
        # 构建用户响应数据
        user_response = {
            "id": str(user["_id"]),
            "username": user.get("username", user.get("email", "")),
            "name": user["name"],
            "email": user["email"],
            "department": user.get("department"),
            "position": user.get("position"),
            "phone": user.get("phone"),
            "avatar": user.get("avatar"),
            "bio": user.get("bio"),
            "status": user.get("status", "active"),
            "is_verified": user.get("is_verified", True),
            "roles": user["roles"],
            "permissions": user["permissions"],
            "created_at": user.get("created_at"),
            "updated_at": user.get("updated_at"),
            "last_login": user.get("last_login"),
            "login_count": user.get("login_count", 0)
        }
        
        return success_response(data=user_response, message="获取用户信息成功")
    except Exception as e:
        return error_response(
            error_type="INTERNAL_ERROR",
            message=f"获取用户资料失败: {str(e)}",
            code=status.HTTP_500_INTERNAL_SERVER_ERROR
        )
@router.put("/me", response_model=ApiResponse, summary="更新当前用户信息")
async def update_current_user_profile(
    profile_update: UserUpdate,
    request: Request,
    current_user: dict = Depends(get_current_user),
    db: AsyncIOMotorDatabase = Depends(get_db)
) -> Any:
    """
    更新当前用户信息
    """
    try:
        from app.utils.activity_logger import ActivityLogger, ActionTypes
        
        # 获取客户端信息
        ip_address = request.client.host if request.client else None
        user_agent = request.headers.get("user-agent", "")
        
        user_id = ObjectId(current_user["user_id"])
        
        # 检查邮箱是否已被其他用户使用
        if profile_update.email:
            existing_user = await db.users.find_one({
                "email": profile_update.email,
                "_id": {"$ne": user_id}
            })
            if existing_user:
                return error_response(
                    error_type="CONFLICT_ERROR",
                    message="邮箱已被其他用户使用",
                    code=status.HTTP_400_BAD_REQUEST
                )
        
        # 准备更新数据
        update_data = {}
        for field, value in profile_update.model_dump(exclude_unset=True).items():
            if value is not None:
                update_data[field] = value
        
        if update_data:
            update_data["updated_at"] = datetime.utcnow()
            
            # 更新用户信息
            result = await db.users.update_one(
                {"_id": user_id},
                {"$set": update_data}
            )
            
            if result.matched_count == 0:
                return error_response(
                    error_type="NOT_FOUND_ERROR",
                    message="用户不存在",
                    code=status.HTTP_404_NOT_FOUND
                )
            
            # 记录资料更新活动
            await ActivityLogger.log_user_action(
                db=db,
                user_id=str(user_id),
                action=ActionTypes.USER_UPDATE_PROFILE,
                description=f"用户 {current_user.get('name', 'Unknown')} 更新了个人资料",
                ip_address=ip_address,
                user_agent=user_agent,
                metadata={"updated_fields": list(update_data.keys())}
            )
        
        # 获取更新后的用户信息
        updated_user = await db.users.find_one({"_id": user_id})
        
        # 构建用户响应数据
        user_response = {
            "id": str(updated_user["_id"]),
            "username": updated_user.get("username", updated_user.get("email", "")),
            "name": updated_user["name"],
            "email": updated_user["email"],
            "department": updated_user.get("department"),
            "position": updated_user.get("position"),
            "phone": updated_user.get("phone"),
            "avatar": updated_user.get("avatar"),
            "bio": updated_user.get("bio"),
            "status": updated_user.get("status", "active"),
            "is_verified": updated_user.get("is_verified", True),
            "roles": updated_user["roles"],
            "permissions": updated_user["permissions"],
            "created_at": updated_user.get("created_at"),
            "updated_at": updated_user.get("updated_at"),
            "last_login": updated_user.get("last_login"),
            "login_count": updated_user.get("login_count", 0)
        }
        
        return success_response(data=user_response, message="用户资料更新成功")
    except HTTPException:
        raise
    except Exception as e:
        return error_response(
            error_type="INTERNAL_ERROR",
            message=f"更新用户资料失败: {str(e)}",
            code=status.HTTP_500_INTERNAL_SERVER_ERROR
        )

@router.post("/avatar", response_model=ApiResponse, summary="上传用户头像")
async def upload_avatar(
    request: Request,
    file: UploadFile = File(...),
    current_user: dict = Depends(get_current_user),
    db: AsyncIOMotorDatabase = Depends(get_db)
) -> Any:
    """
    上传用户头像
    """
    try:
        from app.utils.activity_logger import ActivityLogger, ActionTypes
        
        # 获取客户端信息
        ip_address = request.client.host if request.client else None
        user_agent = request.headers.get("user-agent", "")
        
        # 检查文件类型
        if not file.content_type or not file.content_type.startswith("image/"):
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail="File must be an image"
            )
        
        # 检查文件大小 (5MB)
        if file.size and file.size > 5 * 1024 * 1024:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail="File size must be less than 5MB"
            )
        
        # 生成唯一文件名
        file_extension = file.filename.split(".")[-1] if file.filename else "jpg"
        filename = f"{uuid.uuid4()}.{file_extension}"
        
        # 创建上传目录
        upload_dir = Path(settings.UPLOAD_DIR) / "avatars"
        upload_dir.mkdir(parents=True, exist_ok=True)
        
        # 保存文件
        file_path = upload_dir / filename
        with open(file_path, "wb") as buffer:
            content = await file.read()
            buffer.write(content)
        
        # 构建头像URL
        avatar_url = f"/uploads/avatars/{filename}"
        
        # 更新用户头像
        user_id = ObjectId(current_user["user_id"])
        await db.users.update_one(
            {"_id": user_id},
            {"$set": {"avatar": avatar_url, "updated_at": datetime.utcnow()}}
        )
        
        # 记录头像上传活动
        await ActivityLogger.log_user_action(
            db=db,
            user_id=str(user_id),
            action=ActionTypes.USER_UPLOAD_AVATAR,
            description=f"用户 {current_user.get('name', 'Unknown')} 上传了新头像",
            ip_address=ip_address,
            user_agent=user_agent,
            metadata={"avatar_url": avatar_url, "file_size": len(content)}
        )
        
        return success_response(
            data={"avatar": avatar_url},
            message="头像上传成功"
        )
    
    except HTTPException:
        raise
    except Exception as e:
        return error_response(
            error_type="INTERNAL_ERROR",
            message=f"头像上传失败: {str(e)}",
            code=status.HTTP_500_INTERNAL_SERVER_ERROR
        )

@router.get("/notifications", response_model=ApiResponse, summary="获取用户通知设置")
async def get_notification_settings(
    current_user: dict = Depends(get_current_user),
    db: AsyncIOMotorDatabase = Depends(get_db)
) -> Any:
    """
    获取用户通知设置
    """
    try:
        user_id = ObjectId(current_user["user_id"])
        
        # 查找用户的通知设置
        settings_doc = await db.notification_settings.find_one({"user_id": user_id})
        
        if not settings_doc:
            # 如果没有设置，创建默认设置
            default_settings = {
                "user_id": user_id,
                "email_task_assigned": True,
                "email_task_completed": True,
                "email_project_update": False,
                "email_deadline_reminder": True,
                "system_task_assigned": True,
                "system_task_completed": True,
                "system_project_update": True,
                "system_deadline_reminder": True,
                "created_at": datetime.utcnow(),
                "updated_at": datetime.utcnow()
            }
            
            result = await db.notification_settings.insert_one(default_settings)
            settings_doc = await db.notification_settings.find_one({"_id": result.inserted_id})
        
        settings = NotificationSettingsResponse(
            id=str(settings_doc["_id"]),
            user_id=str(settings_doc["user_id"]),
            email_task_assigned=settings_doc["email_task_assigned"],
            email_task_completed=settings_doc["email_task_completed"],
            email_project_update=settings_doc["email_project_update"],
            email_deadline_reminder=settings_doc["email_deadline_reminder"],
            system_task_assigned=settings_doc["system_task_assigned"],
            system_task_completed=settings_doc["system_task_completed"],
            system_project_update=settings_doc["system_project_update"],
            system_deadline_reminder=settings_doc["system_deadline_reminder"],
            created_at=settings_doc.get("created_at"),
            updated_at=settings_doc.get("updated_at")
        )
        
        return success_response(
            data=settings,
            message="获取通知设置成功"
        )
    
    except HTTPException:
        raise
    except Exception as e:
        return error_response(
            error_type="INTERNAL_ERROR",
            message=f"获取通知设置失败: {str(e)}",
            code=status.HTTP_500_INTERNAL_SERVER_ERROR
        )

@router.put("/notifications", response_model=ApiResponse, summary="更新用户通知设置")
async def update_notification_settings(
    settings_update: NotificationSettings,
    request: Request,
    current_user: dict = Depends(get_current_user),
    db: AsyncIOMotorDatabase = Depends(get_db)
) -> Any:
    """
    更新用户通知设置
    """
    try:
        from app.utils.activity_logger import ActivityLogger, ActionTypes
        
        # 获取客户端信息
        ip_address = request.client.host if request.client else None
        user_agent = request.headers.get("user-agent", "")
        
        user_id = ObjectId(current_user["user_id"])
        
        # 准备更新数据
        update_data = settings_update.model_dump()
        update_data["updated_at"] = datetime.utcnow()
        
        # 更新或创建通知设置
        result = await db.notification_settings.update_one(
            {"user_id": user_id},
            {"$set": update_data},
            upsert=True
        )
        
        # 记录通知设置更新活动
        await ActivityLogger.log_user_action(
            db=db,
            user_id=str(user_id),
            action=ActionTypes.USER_UPDATE_SETTINGS,
            description=f"用户 {current_user.get('name', 'Unknown')} 更新了通知设置",
            ip_address=ip_address,
            user_agent=user_agent,
            metadata=update_data
        )
        
        # 获取更新后的设置
        settings_doc = await db.notification_settings.find_one({"user_id": user_id})
        
        settings = NotificationSettingsResponse(
            id=str(settings_doc["_id"]),
            user_id=str(settings_doc["user_id"]),
            email_task_assigned=settings_doc["email_task_assigned"],
            email_task_completed=settings_doc["email_task_completed"],
            email_project_update=settings_doc["email_project_update"],
            email_deadline_reminder=settings_doc["email_deadline_reminder"],
            system_task_assigned=settings_doc["system_task_assigned"],
            system_task_completed=settings_doc["system_task_completed"],
            system_project_update=settings_doc["system_project_update"],
            system_deadline_reminder=settings_doc["system_deadline_reminder"],
            created_at=settings_doc.get("created_at"),
            updated_at=settings_doc.get("updated_at")
        )
        
        return success_response(
            data=settings,
            message="通知设置更新成功"
        )
    
    except HTTPException:
        raise
    except Exception as e:
        return error_response(
            error_type="INTERNAL_ERROR",
            message=f"更新通知设置失败: {str(e)}",
            code=status.HTTP_500_INTERNAL_SERVER_ERROR
        )

@router.get("/activities", response_model=ApiResponse, summary="获取用户活动记录")
async def get_user_activities(
    page: int = Query(1, ge=1, description="页码"),
    limit: int = Query(20, ge=1, le=100, description="每页数量"),
    action: Optional[str] = Query(None, description="操作类型筛选"),
    target_type: Optional[str] = Query(None, description="目标类型筛选"),
    start_date: Optional[str] = Query(None, description="开始日期 (YYYY-MM-DD)"),
    end_date: Optional[str] = Query(None, description="结束日期 (YYYY-MM-DD)"),
    current_user: dict = Depends(get_current_user),
    db: AsyncIOMotorDatabase = Depends(get_db)
) -> Any:
    """
    获取用户活动记录
    支持按操作类型、目标类型、日期范围筛选
    """
    try:
        from datetime import datetime, timedelta
        
        user_id = current_user["user_id"]
        
        # 构建查询条件
        query = {"user_id": user_id}
        if action:
            query["action"] = action
        if target_type:
            query["target_type"] = target_type
        
        # 日期范围筛选
        if start_date or end_date:
            date_query = {}
            if start_date:
                try:
                    start_datetime = datetime.strptime(start_date, "%Y-%m-%d")
                    date_query["$gte"] = start_datetime
                except ValueError:
                    return error_response(
                        error_type="VALIDATION_ERROR",
                        message="开始日期格式错误，请使用 YYYY-MM-DD 格式",
                        code=status.HTTP_400_BAD_REQUEST
                    )
            if end_date:
                try:
                    end_datetime = datetime.strptime(end_date, "%Y-%m-%d")
                    # 结束日期包含整天，所以设置为当天的23:59:59
                    end_datetime = end_datetime + timedelta(days=1) - timedelta(seconds=1)
                    date_query["$lte"] = end_datetime
                except ValueError:
                    return error_response(
                        error_type="VALIDATION_ERROR",
                        message="结束日期格式错误，请使用 YYYY-MM-DD 格式",
                        code=status.HTTP_400_BAD_REQUEST
                    )
            if date_query:
                query["created_at"] = date_query
        
        # 计算跳过的记录数
        skip = (page - 1) * limit
        
        # 获取总数
        total = await db.activity_logs.count_documents(query)
        
        # 获取活动记录
        activities = await db.activity_logs.find(query)\
            .sort("created_at", -1)\
            .skip(skip)\
            .limit(limit)\
            .to_list(length=None)
        
        # 获取用户信息（用于显示用户名）
        user_ids = list(set([activity["user_id"] for activity in activities]))
        users_dict = {}
        if user_ids:
            users = await db.users.find(
                {"_id": {"$in": [ObjectId(uid) for uid in user_ids]}}
            ).to_list(length=None)
            users_dict = {str(user["_id"]): user for user in users}
        
        # 转换为响应格式
        activity_list = []
        for activity in activities:
            user_info = users_dict.get(activity["user_id"], {})
            activity_list.append({
                "id": str(activity["_id"]),
                "user_id": activity["user_id"],
                "user_name": user_info.get("name") or user_info.get("username", ""),
                "action": activity["action"],
                "target_type": activity["target_type"],
                "target_id": activity["target_id"],
                "target_name": activity.get("target_name", ""),
                "description": activity.get("description", ""),
                "ip_address": activity.get("ip_address"),
                "user_agent": activity.get("user_agent"),
                "metadata": activity.get("metadata", {}),
                "created_at": activity.get("created_at")
            })
        
        activity_log_list = ActivityLogList(
            total=total,
            page=page,
            limit=limit,
            data=activity_list
        )
        
        return success_response(
            data=activity_log_list,
            message="获取用户活动记录成功"
        )
    
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"获取用户活动记录失败: {str(e)}", exc_info=True)
        return error_response(
            error_type="INTERNAL_ERROR",
            message=f"获取用户活动记录失败: {str(e)}",
            code=status.HTTP_500_INTERNAL_SERVER_ERROR
        )

@router.get("/login-logs", response_model=ApiResponse, summary="获取用户登录日志")
async def get_user_login_logs(
    page: int = 1,
    limit: int = 20,
    current_user: dict = Depends(get_current_user),
    db: AsyncIOMotorDatabase = Depends(get_db)
) -> Any:
    """
    获取用户登录日志
    """
    try:
        user_id = current_user["user_id"]
        
        # 计算跳过的记录数
        skip = (page - 1) * limit
        
        # 获取总数
        total = await db.login_logs.count_documents({"user_id": user_id})
        
        # 获取登录日志
        logs = await db.login_logs.find({"user_id": user_id})\
            .sort("login_time", -1)\
            .skip(skip)\
            .limit(limit)\
            .to_list(length=None)
        
        # 转换为响应格式
        log_list = []
        for log in logs:
            log_list.append({
                "id": str(log["_id"]),
                "user_id": log["user_id"],
                "ip_address": log["ip_address"],
                "user_agent": log["user_agent"],
                "device_info": log.get("device_info"),
                "success": log["success"],
                "login_time": log["login_time"]
            })
        
        login_log_list = LoginLogList(
            total=total,
            page=page,
            limit=limit,
            data=log_list
        )
        
        return success_response(
            data=login_log_list,
            message="获取登录日志成功"
        )
    
    except Exception as e:
        return error_response(
            error_type="INTERNAL_ERROR",
            message=f"获取登录日志失败: {str(e)}",
            code=status.HTTP_500_INTERNAL_SERVER_ERROR
        )

@router.get("/stats", response_model=ApiResponse, summary="获取用户统计数据")
async def get_user_stats(
    current_user: dict = Depends(get_current_user),
    db: AsyncIOMotorDatabase = Depends(get_db)
) -> Any:
    """
    获取用户统计数据
    """
    try:
        user_id = current_user["user_id"]
        
        # 获取项目统计
        project_pipeline = [
            {"$match": {"members.user_id": user_id}},
            {"$group": {
                "_id": "$status",
                "count": {"$sum": 1}
            }}
        ]
        project_stats = await db.projects.aggregate(project_pipeline).to_list(length=None)
        
        total_projects = sum(stat["count"] for stat in project_stats)
        active_projects = sum(stat["count"] for stat in project_stats if stat["_id"] in ["active", "planning"])
        completed_projects = sum(stat["count"] for stat in project_stats if stat["_id"] == "completed")
        
        # 获取任务统计
        task_pipeline = [
            {"$match": {"assignee": user_id}},
            {"$group": {
                "_id": "$status",
                "count": {"$sum": 1},
                "total_hours": {"$sum": "$actual_hours"}
            }}
        ]
        task_stats = await db.tasks.aggregate(task_pipeline).to_list(length=None)
        
        total_tasks = sum(stat["count"] for stat in task_stats)
        completed_tasks = sum(stat["count"] for stat in task_stats if stat["_id"] == "completed")
        in_progress_tasks = sum(stat["count"] for stat in task_stats if stat["_id"] == "in_progress")
        
        # 计算逾期任务
        current_time = datetime.utcnow()
        overdue_tasks = await db.tasks.count_documents({
            "assignee": user_id,
            "status": {"$ne": "completed"},
            "due_date": {"$lt": current_time}
        })
        
        # 计算工时统计
        total_work_hours = sum(stat["total_hours"] for stat in task_stats if stat.get("total_hours"))
        
        # 本月工时
        start_of_month = datetime.utcnow().replace(day=1, hour=0, minute=0, second=0, microsecond=0)
        this_month_pipeline = [
            {"$match": {
                "assignee": user_id,
                "updated_at": {"$gte": start_of_month}
            }},
            {"$group": {
                "_id": None,
                "total_hours": {"$sum": "$actual_hours"}
            }}
        ]
        month_result = await db.tasks.aggregate(this_month_pipeline).to_list(length=None)
        this_month_hours = month_result[0]["total_hours"] if month_result else 0
        
        # 本周工时
        start_of_week = datetime.utcnow() - timedelta(days=datetime.utcnow().weekday())
        start_of_week = start_of_week.replace(hour=0, minute=0, second=0, microsecond=0)
        this_week_pipeline = [
            {"$match": {
                "assignee": user_id,
                "updated_at": {"$gte": start_of_week}
            }},
            {"$group": {
                "_id": None,
                "total_hours": {"$sum": "$actual_hours"}
            }}
        ]
        week_result = await db.tasks.aggregate(this_week_pipeline).to_list(length=None)
        this_week_hours = week_result[0]["total_hours"] if week_result else 0
        
        # 计算完成率
        task_completion_rate = (completed_tasks / total_tasks * 100) if total_tasks > 0 else 0
        
        # 获取最近项目
        recent_projects = await db.projects.find(
            {"members.user_id": user_id}
        ).sort("updated_at", -1).limit(5).to_list(length=None)
        
        project_list = []
        for project in recent_projects:
            # 计算项目任务统计
            project_task_stats = await db.tasks.aggregate([
                {"$match": {"project_id": str(project["_id"])}},
                {"$group": {
                    "_id": "$status",
                    "count": {"$sum": 1},
                    "hours": {"$sum": "$actual_hours"}
                }}
            ]).to_list(length=None)
            
            project_total_tasks = sum(stat["count"] for stat in project_task_stats)
            project_completed_tasks = sum(stat["count"] for stat in project_task_stats if stat["_id"] == "completed")
            project_completion_rate = (project_completed_tasks / project_total_tasks * 100) if project_total_tasks > 0 else 0
            project_work_hours = sum(stat["hours"] for stat in project_task_stats if stat.get("hours"))
            
            project_list.append({
                "project_id": str(project["_id"]),
                "project_name": project["name"],
                "total_tasks": project_total_tasks,
                "completed_tasks": project_completed_tasks,
                "completion_rate": project_completion_rate,
                "work_hours": project_work_hours
            })
        
        # 获取最近任务
        recent_tasks = await db.tasks.find(
            {"assignee": user_id}
        ).sort("updated_at", -1).limit(10).to_list(length=None)
        
        task_list = []
        for task in recent_tasks:
            task_list.append({
                "task_id": str(task["_id"]),
                "task_title": task["title"],
                "status": task["status"],
                "priority": task["priority"],
                "work_hours": task.get("actual_hours", 0),
                "created_at": task.get("created_at"),
                "completed_at": task.get("completed_at")
            })
        
        # 工时趋势（最近7天）
        work_hour_trend = []
        for i in range(7):
            date = datetime.utcnow() - timedelta(days=i)
            start_date = date.replace(hour=0, minute=0, second=0, microsecond=0)
            end_date = start_date + timedelta(days=1)
            
            daily_hours = await db.tasks.aggregate([
                {"$match": {
                    "assignee": user_id,
                    "updated_at": {"$gte": start_date, "$lt": end_date}
                }},
                {"$group": {
                    "_id": None,
                    "total_hours": {"$sum": "$actual_hours"}
                }}
            ]).to_list(length=None)
            
            hours = daily_hours[0]["total_hours"] if daily_hours else 0
            work_hour_trend.append({
                "date": start_date.strftime("%Y-%m-%d"),
                "hours": hours
            })
        
        work_hour_trend.reverse()  # 按时间正序排列
        
        # 计算平均完成时间（已完成任务的创建到完成的时间差，单位：小时）
        avg_completion_time = 0.0
        if completed_tasks > 0:
            completed_tasks_with_dates = await db.tasks.find(
                {
                    "assignee": user_id,
                    "status": done_status_code,
                    "created_at": {"$exists": True},
                    "completed_at": {"$exists": True}
                },
                {"created_at": 1, "completed_at": 1}
            ).to_list(length=None)
            
            if completed_tasks_with_dates:
                total_completion_time = 0.0
                valid_tasks = 0
                for task in completed_tasks_with_dates:
                    created_at = task.get("created_at")
                    completed_at = task.get("completed_at")
                    if created_at and completed_at:
                        # 计算时间差（小时）
                        if isinstance(created_at, datetime) and isinstance(completed_at, datetime):
                            time_diff = (completed_at - created_at).total_seconds() / 3600
                            if time_diff > 0:  # 只统计有效的时间差
                                total_completion_time += time_diff
                                valid_tasks += 1
                
                if valid_tasks > 0:
                    avg_completion_time = round(total_completion_time / valid_tasks, 2)
        
        # 计算按时完成率（在截止日期前完成的任务比例）
        on_time_completion_rate = 0.0
        if completed_tasks > 0:
            # 获取所有已完成且有截止日期的任务
            completed_tasks_with_due_date = await db.tasks.find(
                {
                    "assignee": user_id,
                    "status": done_status_code,
                    "due_date": {"$exists": True, "$ne": None},
                    "completed_at": {"$exists": True, "$ne": None}
                },
                {"due_date": 1, "completed_at": 1}
            ).to_list(length=None)
            
            if completed_tasks_with_due_date:
                on_time_count = 0
                for task in completed_tasks_with_due_date:
                    due_date = task.get("due_date")
                    completed_at = task.get("completed_at")
                    if due_date and completed_at:
                        # 确保都是datetime类型
                        if isinstance(due_date, str):
                            try:
                                due_date = datetime.fromisoformat(due_date.replace('Z', '+00:00'))
                            except:
                                continue
                        if isinstance(completed_at, str):
                            try:
                                completed_at = datetime.fromisoformat(completed_at.replace('Z', '+00:00'))
                            except:
                                continue
                        
                        # 如果完成时间在截止日期之前或当天，视为按时完成
                        if isinstance(due_date, datetime) and isinstance(completed_at, datetime):
                            # 比较日期部分（忽略时间）
                            due_date_only = due_date.replace(hour=23, minute=59, second=59)
                            if completed_at <= due_date_only:
                                on_time_count += 1
                
                if len(completed_tasks_with_due_date) > 0:
                    on_time_completion_rate = round((on_time_count / len(completed_tasks_with_due_date)) * 100, 2)
        
        # 构建响应
        user_stats_data = {
            "user_id": user_id,
            "total_projects": total_projects,
            "active_projects": active_projects,
            "completed_projects": completed_projects,
            "total_tasks": total_tasks,
            "completed_tasks": completed_tasks,
            "in_progress_tasks": in_progress_tasks,
            "overdue_tasks": overdue_tasks,
            "total_work_hours": total_work_hours,
            "this_month_hours": this_month_hours,
            "this_week_hours": this_week_hours,
            "avg_task_completion_time": avg_completion_time,
            "task_completion_rate": task_completion_rate,
            "on_time_completion_rate": on_time_completion_rate
        }
        
        user_stats_response = UserStatsResponse(
            user_stats=user_stats_data,
            recent_projects=project_list,
            recent_tasks=task_list,
            work_hour_trend=work_hour_trend
        )
        
        return success_response(
            data=user_stats_response,
            message="获取用户统计成功"
        )
    
    except Exception as e:
        return error_response(
            error_type="INTERNAL_ERROR",
            message=f"获取用户统计失败: {str(e)}",
            code=status.HTTP_500_INTERNAL_SERVER_ERROR
        )

@router.get("/dashboard", response_model=ApiResponse, summary="获取用户仪表盘统计")
async def get_dashboard_stats(
    current_user: dict = Depends(get_current_user),
    db: AsyncIOMotorDatabase = Depends(get_db)
) -> Any:
    """
    获取仪表盘统计数据
    """
    try:
        user_id = current_user["user_id"]
        
        # 项目统计
        total_projects = await db.projects.count_documents({"members.user_id": user_id})
        active_projects = await db.projects.count_documents({
            "members.user_id": user_id,
            "status": {"$in": ["active", "planning"]}
        })
        
        # 任务统计 - 使用动态状态
        from app.utils.state_utils import get_state_code_by_name_keywords
        
        done_status_code = await get_state_code_by_name_keywords(db, "task", ["已完成", "完成", "done", "completed"])
        todo_status_code = await get_state_code_by_name_keywords(db, "task", ["待办", "待处理", "todo", "new"])
        
        total_tasks = await db.tasks.count_documents({"assignee": user_id})
        completed_tasks = await db.tasks.count_documents({"assignee": user_id, "status": done_status_code}) if done_status_code else 0
        pending_tasks = await db.tasks.count_documents({"assignee": user_id, "status": todo_status_code}) if todo_status_code else 0
        
        # 逾期任务
        current_time = datetime.utcnow()
        overdue_tasks = await db.tasks.count_documents({
            "assignee": user_id,
            "status": {"$ne": "completed"},
            "due_date": {"$lt": current_time}
        })
        
        # 工时统计
        total_hours_result = await db.tasks.aggregate([
            {"$match": {"assignee": user_id}},
            {"$group": {"_id": None, "total_hours": {"$sum": "$actual_hours"}}}
        ]).to_list(length=None)
        total_work_hours = total_hours_result[0]["total_hours"] if total_hours_result else 0
        
        # 本月工时
        start_of_month = datetime.utcnow().replace(day=1, hour=0, minute=0, second=0, microsecond=0)
        month_hours_result = await db.tasks.aggregate([
            {"$match": {
                "assignee": user_id,
                "updated_at": {"$gte": start_of_month}
            }},
            {"$group": {"_id": None, "total_hours": {"$sum": "$actual_hours"}}}
        ]).to_list(length=None)
        this_month_hours = month_hours_result[0]["total_hours"] if month_hours_result else 0
        
        # 计算完成率和生产力评分
        completion_rate = (completed_tasks / total_tasks * 100) if total_tasks > 0 else 0
        productivity_score = min(completion_rate * 0.7 + (this_month_hours / 160 * 100) * 0.3, 100)
        
        dashboard_stats = DashboardStats(
            total_projects=total_projects,
            active_projects=active_projects,
            total_tasks=total_tasks,
            completed_tasks=completed_tasks,
            pending_tasks=pending_tasks,
            overdue_tasks=overdue_tasks,
            total_work_hours=total_work_hours,
            this_month_hours=this_month_hours,
            productivity_score=productivity_score,
            completion_rate=completion_rate
        )
        
        return success_response(
            data=dashboard_stats,
            message="获取仪表盘统计成功"
        )
    
    except HTTPException:
        raise
    except Exception as e:
        return error_response(
            error_type="INTERNAL_ERROR",
            message=f"获取仪表盘统计失败: {str(e)}",
            code=status.HTTP_500_INTERNAL_SERVER_ERROR
        )

@router.get("/preferences", response_model=ApiResponse, summary="获取用户偏好设置")
async def get_user_preferences(
    current_user: dict = Depends(get_current_user),
    db: AsyncIOMotorDatabase = Depends(get_db)
) -> Any:
    """
    获取用户偏好设置
    """
    try:
        user_id = ObjectId(current_user["user_id"])
        
        # 查找用户的偏好设置
        preferences_doc = await db.user_preferences.find_one({"user_id": user_id})
        
        if not preferences_doc:
            # 如果没有设置，创建默认设置
            default_preferences = {
                "user_id": user_id,
                "theme": "light",
                "language": "zh-CN",
                "timezone": "Asia/Shanghai",
                "created_at": datetime.utcnow(),
                "updated_at": datetime.utcnow()
            }
            
            result = await db.user_preferences.insert_one(default_preferences)
            preferences_doc = await db.user_preferences.find_one({"_id": result.inserted_id})
        
        preferences = UserPreferences(
            theme=preferences_doc.get("theme", "light"),
            language=preferences_doc.get("language", "zh-CN"),
            timezone=preferences_doc.get("timezone", "Asia/Shanghai")
        )
        
        return success_response(
            data=preferences.model_dump(),
            message="获取用户偏好设置成功"
        )
    
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"获取用户偏好设置失败: {str(e)}", exc_info=True)
        return error_response(
            error_type="INTERNAL_ERROR",
            message=f"获取用户偏好设置失败: {str(e)}",
            code=status.HTTP_500_INTERNAL_SERVER_ERROR
        )

@router.put("/preferences", response_model=ApiResponse, summary="更新用户偏好设置")
async def update_user_preferences(
    preferences_update: UserPreferencesUpdate,
    request: Request,
    current_user: dict = Depends(get_current_user),
    db: AsyncIOMotorDatabase = Depends(get_db)
) -> Any:
    """
    更新用户偏好设置
    """
    try:
        from app.utils.activity_logger import ActivityLogger, ActionTypes
        
        # 获取客户端信息
        ip_address = request.client.host if request.client else None
        user_agent = request.headers.get("user-agent", "")
        
        user_id = ObjectId(current_user["user_id"])
        
        # 准备更新数据（只包含非None的字段）
        update_data = {}
        for field, value in preferences_update.model_dump(exclude_unset=True).items():
            if value is not None:
                update_data[field] = value
        
        if not update_data:
            return error_response(
                error_type="VALIDATION_ERROR",
                message="没有需要更新的字段",
                code=status.HTTP_400_BAD_REQUEST
            )
        
        update_data["updated_at"] = datetime.utcnow()
        
        # 如果不存在，先创建
        existing_prefs = await db.user_preferences.find_one({"user_id": user_id})
        if not existing_prefs:
            update_data["user_id"] = user_id
            update_data["created_at"] = datetime.utcnow()
            await db.user_preferences.insert_one(update_data)
        else:
            # 更新或创建偏好设置
            await db.user_preferences.update_one(
                {"user_id": user_id},
                {"$set": update_data},
                upsert=True
            )
        
        # 记录偏好设置更新活动
        await ActivityLogger.log_user_action(
            db=db,
            user_id=str(user_id),
            action=ActionTypes.USER_UPDATE_SETTINGS,
            description=f"用户 {current_user.get('name', 'Unknown')} 更新了偏好设置",
            ip_address=ip_address,
            user_agent=user_agent,
            metadata=update_data
        )
        
        # 获取更新后的设置
        preferences_doc = await db.user_preferences.find_one({"user_id": user_id})
        
        preferences = UserPreferences(
            theme=preferences_doc.get("theme", "light"),
            language=preferences_doc.get("language", "zh-CN"),
            timezone=preferences_doc.get("timezone", "Asia/Shanghai")
        )
        
        return success_response(
            data=preferences.model_dump(),
            message="用户偏好设置更新成功"
        )
    
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"更新用户偏好设置失败: {str(e)}", exc_info=True)
        return error_response(
            error_type="INTERNAL_ERROR",
            message=f"更新用户偏好设置失败: {str(e)}",
            code=status.HTTP_500_INTERNAL_SERVER_ERROR
        )